package com.hhqk.shiro;

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import com.hhqk.model.User;
import com.hhqk.service.UserService;

public class AuthRealm extends AuthorizingRealm{
	@Autowired
	private UserService userService;
	
	/*
	 * 这个方法是实现授权管理的
	 * shiro授权的实现原理：
	 * 1.shiro加载页面，会判断是否含有<shiro:hasPermission>
	 * 2.shiro会把所有的<shiro:hasPermission里的name属性形成一个集合，比如PermissionList
	 * 3.用户登录认证成功之后，会调用AuthorizationInfo这个方法
	 * 4.这个方法会返回一个info的信息，这个信息里，存储来的用户的授权资料，也是一个集合userPermissionList
	 * 5.shiro 和拿PermissionList和 userPermissionList做比对，如果用户有相应的权限的话，页面就展示
	 * 否则就不予以展示
	 * 
	 * 
	 * 当前的授权资料，是我们自己写死的。实际情况，应该通过用户的信息来查出来
	 * 实现思路：
	 * 1.当用户登录成功之后，把用户名存在session域里，然后在本方法里通过Session取出来
	 * 2.用shiro的Session来做
	 * 3.从session域里拿出username之后，就可以根据username去查角色，继而查角色对应的权限模块
	 * 
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		Subject subject=SecurityUtils.getSubject();
		//得到用户名之后，接下来，就是根据用户名去查询用户对应的角色，查询出角色之后，就可以查询角色对应的模块
		String username=(String) subject.getSession().getAttribute("username");
		List<String> infoList=new ArrayList<>();
		infoList.add("系统首页");
		infoList.add("货运管理");
		infoList.add("基础信息");
		infoList.add("系统管理");
		//这一步，相当于在创建授权管理员
		SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
		//这一步，调用授权管理上的方法，把集合传过去
		info.addStringPermissions(infoList);
		//最后，交给shiro去做授权管理
		return info;
	}
	//登录认证模块，相关的认证方法在这里写。
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//1.把token对象 由AuthenticationToken强转成 UsernamePasswordToken
		UsernamePasswordToken loginToken=(UsernamePasswordToken) token;
		//2.通过loginToken,得到当前用户输入的用户名
		String username=loginToken.getUsername();
		//3.后台根据用户名，去数据库里查询，得到对应的用户对象
		User user=userService.findUserByUsername(username);
		//4.以上三步都做好之后，把shiro的登录认证管理员叫出来，把资料交给他，他会自动的去做登录认证
		//需要提供的资料：①当前的用户对象 ②当前用户的真实密码  ③当前AuthRealm的名字（全路径名），直接调用this.getName()即可
		
		AuthenticationInfo info =new SimpleAuthenticationInfo(
				user,user.getPassword(),this.getName());
		//return info之后，shiro就可以做登录认证了
		//所谓的登录认证，实际上就是在匹配用户的真实密码和用户在页面上输入的密码。
		//用户的输入密码，shiro已经在token,进行了存储。所以我们只需要把用户的真实密码资料提交给shiro即可
		//shiro会自动去做密码的匹配的
		return info;
	}
	

}
